package io.github.kouleen.breadlib.processor;

import io.github.kouleen.breadlib.annotation.Main;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.*;
import java.util.Set;

/**
 * @author zhangqing
 * @since 2023/2/23 12:26
 */
@SupportedAnnotationTypes("io.github.kouleen.breadlib.annotation.MySetterGetter")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class ApplicationProcessor extends AbstractProcessor {

    private boolean isProcess = false;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Main.class);
        for (Element element : elements) {
            if (isProcess) {
                throw new IllegalStateException("There can only be one plugin Main");
            }
            isProcess = true;
            File file = new File(new File("/").getAbsolutePath() + "/io.github.kouleen.breadlib.txt");
            try {
                if(!file.exists()){
                    file.createNewFile();
                }
            }catch (Exception exception){
                exception.printStackTrace();
            }
            Elements elementUtils = processingEnv.getElementUtils();
            // 获取包名
            PackageElement packageElement = elementUtils.getPackageOf(element);
            String packageName = packageElement.getQualifiedName().toString();
            note(String.format("packageName = %s", packageName));

            // 获取包装类类型
            TypeElement typeElement = (TypeElement)element.getEnclosingElement();
            String enclosingName = typeElement.getQualifiedName().toString();
            note(String.format("enclosingName = %s", enclosingName));

            // 因为BindView只作用于filed，所以这里可直接进行强转
            VariableElement variableElement = (VariableElement)element;
            // 获取注解的成员变量名
            String mainFiledName  = variableElement.getSimpleName().toString();
            // 获取注解的成员变量类型
            String mainFiledClassType  = variableElement.asType().toString();

            note(String.format("%s %s", mainFiledName, mainFiledClassType));
            try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
                System.out.println("##############################");
                bufferedWriter.write("##############################\n");
                System.out.println("#          BreadLib          #");
                bufferedWriter.write("#          BreadLib          #\n");
                System.out.println("##############################");
                bufferedWriter.write("##############################\n");
                bufferedWriter.write("\n");
                bufferedWriter.write("\n");
                bufferedWriter.write("version: 1.0.0\n");
                bufferedWriter.write("author : kouleen\n");
                bufferedWriter.write("author : kouleen\n");
            }catch (Exception exception){
                exception.printStackTrace();
            }
            createFile(typeElement,mainFiledClassType,mainFiledName);

        }
        return true;
    }

    private void createFile(TypeElement typeElement, String mainFiledClassType, String mainFiledName) {
        Elements elementUtils = processingEnv.getElementUtils();
        String packageName = elementUtils.getPackageOf(typeElement).getQualifiedName().toString();
        try {
            JavaFileObject jfo = processingEnv.getFiler().createSourceFile(packageName + ".ViewBinding", new Element[]{});
            Writer writer = jfo.openWriter();
            writer.write(brewCode(packageName, mainFiledClassType, mainFiledName));
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String brewCode(String packageName, String mainFiledClassType, String mainFiledName) {
        StringBuilder builder = new StringBuilder();
        builder.append("package ").append(packageName).append(";\n\n");
        builder.append("//Auto generated by apt,do not modify!!\n\n");
        builder.append("public class Main { \n\n");
        builder.append("public static void main(String[] args){ \n");
        String info = String.format("%s %s", mainFiledClassType, mainFiledName);
        builder.append("System.out.println(\"").append(info).append("\");\n");
        builder.append("}\n");
        builder.append("}");
        return builder.toString();
    }

    private void note(String message) {
        Messager messager = processingEnv.getMessager();
        messager.printMessage(Diagnostic.Kind.NOTE, message);
    }

    private void note(String format, Object... args) {
        Messager messager = processingEnv.getMessager();
        messager.printMessage(Diagnostic.Kind.NOTE, String.format(format, args));
    }
}
